package com.ziyucoding.springboot.labs.lab10.seatdemo.tccscfeign.productservice.service.impl;

import com.ziyucoding.springboot.labs.lab10.seatdemo.tccscfeign.productservice.dao.ProductDao;
import com.ziyucoding.springboot.labs.lab10.seatdemo.tccscfeign.productservice.service.ProductService;
import io.seata.core.context.RootContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 商品 service实现类
 *
 * @author ziyucoding
 * @date 2022-11-04
 **/
@Service
public class ProductServiceImpl implements ProductService {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private ProductDao productDao;

    @Override
    public Integer getStock(Long productId) throws Exception {
        return productDao.getStock(productId);
    }

    @Override
    public Integer getFrozenStock(Long productId) throws Exception {
        return productDao.getFrozenStock(productId);
    }

    @Override
    @Transactional
    public void frozenStock(Long productId, Integer amount) throws Exception {
        logger.info("[frozenStock] 当前 XID: {}", RootContext.getXID());

        // 检查库存
        checkStock(productId, amount);

        logger.info("[frozenStock] 开始冻结 {} 库存", productId);
        // 冻结库存
        int updateCount = productDao.frozenStock(productId, amount);
        // 冻结成功
        if (updateCount == 0) {
            logger.warn("[frozenStock] 冻结 {} 库存失败", productId);
            throw new Exception("库存不足");
        }
        // 冻结失败
        logger.info("[frozenStock] 冻结 {} 库存成功", productId);
    }

    @Override
    @Transactional
    public void cleanFrozenStock(Long productId, Integer amount) throws Exception {
        logger.info("[cleanFrozenStock] 当前 XID: {}", RootContext.getXID());

        // 检查库存
        checkStock(productId, amount);

        logger.info("[cleanFrozenStock] 开始释放冻结 {} 库存", productId);
        // 冻结库存
        int updateCount = productDao.cleanFrozenStock(productId, amount);
        // 冻结成功
        if (updateCount == 0) {
            logger.warn("[cleanFrozenStock] 释放冻结 {} 库存失败", productId);
            throw new Exception("冻结库存不足");
        }
        // 冻结失败
        logger.info("[cleanFrozenStock] 释放冻结 {} 库存成功", productId);
    }

    @Override
    @Transactional
    public void rollbackFrozenStock(Long productId, Integer amount) throws Exception {
        logger.info("[rollbackFrozenStock] 当前 XID: {}", RootContext.getXID());

        // 检查库存
        checkFrozenStock(productId, amount);

        logger.info("[rollbackFrozenStock] 开始回滚冻结 {} 库存", productId);
        // 冻结库存
        int updateCount = productDao.rollbackFrozenStock(productId, amount);
        // 冻结成功
        if (updateCount == 0) {
            logger.warn("[rollbackFrozenStock] 回滚冻结 {} 库存失败", productId);
            throw new Exception("冻结库存不足");
        }
        // 冻结失败
        logger.info("[rollbackFrozenStock] 回滚冻结 {} 库存成功", productId);
    }

    /**
     * 检查库存
     *
     * @param productId
     * @param requiredAmount
     * @return void
     **/
    private void checkStock(Long productId, Integer requiredAmount) throws Exception {
        logger.info("[checkStock] 检查 {} 库存", productId);
        Integer stock = productDao.getStock(productId);
        if (stock < requiredAmount) {
            logger.warn("[checkStock] {} 库存不足，当前库存: {}", productId, stock);
            throw new Exception("库存不足");
        }
    }

    /**
     * 检查冻结库存
     *
     * @param productId
     * @param requiredAmount
     * @return void
     **/
    private void checkFrozenStock(Long productId, Integer requiredAmount) throws Exception {
        logger.info("[checkFrozenStock] 检查 冻结 {} 库存", productId);
        Integer stock = productDao.getFrozenStock(productId);
        if (stock < requiredAmount) {
            logger.warn("[checkFrozenStock] 冻结 {} 库存不足，当前冻结库存: {}", productId, stock);
            throw new Exception("冻结库存不足");
        }
    }

}
